<?php
/**
 * Created by PhpStorm.
 * User: cy
 * Date: 18-1-10
 * Time: 下午5:06
 * 一致性哈希算法
 */
class  FlexiHash
{
    private $serverList=[];//服务器列表
    private $isSorted=false;//记录数组是否需要排序
    private $mul=64;//每台服务器定义64个虚拟节点

    /**
     * 名称：自定义hash算法
     */
    private function customHash($key)
    {
        $md5=substr(md5($key),0,8);
        $seed=31;
        $hash=0;
        for($i=0;$i<8;$i++){
            $hash=$hash*$seed+ord($md5{$i});
            $i++;
        }
        return $hash & 0x7FFFFFFF;
    }

    /**
     * 名称：添加服务器
     * 必要条件：添加服务器，传入数组
     */
    public function addServers($servers)
    {
        if(!is_array($servers)){
            return false;
        }
        foreach ($servers as $v){
            for($i=0;$i<$this->mul;$i++){
                $node=$v.'-'.$i;
                if(!isset($this->serverList[$this->customHash($node)])){
                    $this->serverList[$this->customHash($node)]=$v;
                }
            }
        }
        $this->isSorted=false;
        return true;
    }

    /**
     * 名称：删除单台服务器
     */
    public function removeServer($server)
    {
        foreach ($this->serverList as $k=>$v){
            if($v==$server){
                unset($this->serverList[$k]);
            }
        }
        $this->isSorted=false;
        return true;
    }

    /**
     * 名称：根据key值获取所在服务器的key
     */
    public function lookup($key)
    {
        $hash=$this->customHash($key);
        if(!$this->isSorted){
            //需要排序,从大到小
            krsort($this->serverList);
            $this->isSorted=true;
        }
        foreach ($this->serverList as $k => $v){
            if($hash>=$k){
                return $v;
            }
        }

        //没有找到则返回最后一个
        return $this->serverList[count($this->serverList)-1];
    }
}